#include "webserver.h"
#include "custom_handle.h"
#include "shmem.h"
static struct shm_param para;

static int *total = NULL;                // 指向共享内存中数据节点总个数
static struct std_node *node_arr = NULL; // 指向共享内存中数组节点缓存数组头
// 全局变量定义
int msgid = -1;
int g_shmid = -1;
char* g_shm_ptr = NULL;



// 从共享内存读取温湿度数据
int read_sensor_data(SensorData *data) {
    if (!g_shm_ptr) return -1;
    
    // 假设共享内存中数据格式为"temperature:25.5 humidity:60.0"
    if (sscanf(g_shm_ptr, "temperature:%f humidity:%f", 
              &data->temperature, &data->humidity) != 2) {
        fprintf(stderr, "共享内存数据格式错误: %s\n", g_shm_ptr);
        return -1;
    }
    return 0;
}

// 处理获取温湿度数据的请求
void handle_sensor_data(int client_socket) {
    SensorData data;
    if (read_sensor_data(&data) == 0) {
        char response[256];
        snprintf(response, sizeof(response),
                "{\"temperature\": %.1f, \"humidity\": %.1f}",
                data.temperature, data.humidity);
        send_response(client_socket, 200, "application/json", response);
    } else {
        send_response(client_socket, 500, "text/plain", "Internal Server Error");
    }
}

int main() {
    // 初始化消息队列
    msgid = msgget(MSG_KEY, IPC_CREAT | 0666);
    if (msgid == -1) {
        perror("msgget failed");
        exit(EXIT_FAILURE);
    }
    printf("消息队列创建成功，ID: %d\n", msgid);

    // // 初始化共享内存
    // key_t shm_key = ftok("/tmp", 'G');
    // g_shmid = shmget(shm_key, 128, IPC_CREAT | 0666);
    // if (g_shmid == -1) {
    //     perror("shmget failed");
    //     exit(EXIT_FAILURE);
    // }
    // g_shm_ptr = shmat(g_shmid, NULL, 0);
    // if (g_shm_ptr == (char*)-1) {
    //     perror("shmat failed");
    //     exit(EXIT_FAILURE);
    // }
    // strcpy(g_shm_ptr, "temperature:0.0 humidity:0.0");
    // printf("共享内存初始化成功，ID: %d\n", g_shmid);

    int ret = shm_init(&para, "shm_test", 1024);
    if (ret < 0)
    {
        printf("共享内存初始化失败\n");
        return -1;
    }
    void *node_p = shm_getaddr(&para);
    if (NULL == node_p)
    {
        printf("共享内存获取地址失败\n");
        return -1;
    }

    total = (int *)node_p;
    *total = 12;
    // printf("%d\n",*total);
    node_arr = (struct std_node *)(node_p + sizeof(int));

    // 创建服务器套接字
    int server_fd, client_socket;
    struct sockaddr_in server_addr, client_addr;
    socklen_t addr_len = sizeof(client_addr);

    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket创建失败");
        exit(EXIT_FAILURE);
    }

    // 设置套接字选项
    int opt = 1;
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
        perror("setsockopt失败");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    // 绑定服务器地址
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);

    if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind失败");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    // 开始监听
    if (listen(server_fd, 10) < 0) {
        perror("listen失败");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    printf("🚀 服务器已启动，监听端口 %d\n", PORT);

    // 主循环处理客户端请求
    while (1) {
        if ((client_socket = accept(server_fd, (struct sockaddr *)&client_addr, &addr_len)) < 0) {
            perror("accept失败");
            continue;
        }

        char buffer[BUFFER_SIZE] = {0};
        ssize_t bytes_read = read(client_socket, buffer, BUFFER_SIZE - 1);
        if (bytes_read <= 0) {
            close(client_socket);
            continue;
        }

        // 解析HTTP请求
        HttpRequest req = {0};
        parse_request(buffer, &req);

        // 处理OPTIONS预检请求
        if (strcmp(req.method, "OPTIONS") == 0) {
            const char *response =
                "HTTP/1.1 204 No Content\r\n"
                "Access-Control-Allow-Origin: *\r\n"
                "Access-Control-Allow-Methods: POST, GET, OPTIONS\r\n"
                "Access-Control-Allow-Headers: Content-Type\r\n"
                "Access-Control-Max-Age: 86400\r\n"
                "Content-Length: 0\r\n"
                "Connection: close\r\n\r\n";
            write(client_socket, response, strlen(response));
            close(client_socket);
            continue;
        }

        // 路由处理
        if (strcmp(req.method, "GET") == 0 && strcmp(req.path, "/sensor_data") == 0) {
            handle_sensor_data(client_socket);
        }
        else if (strcmp(req.method, "POST") == 0 && strcmp(req.path, "/control") == 0) {
            handle_string_control(client_socket, req.body);
        }
        else if (strcmp(req.method, "GET") == 0 && strcmp(req.path, "/get") == 0) {
            handle_get(client_socket, req.path);
        }
        else if (strcmp(req.method, "GET") == 0 && strcmp(req.path, "/device_status") == 0) {
            handle_device_status(client_socket);
        }
        else {
            send_response(client_socket, 404, "text/html", "<h1>404 Not Found</h1>");
        }

        close(client_socket);
    }

    close(server_fd);
    return 0;
}

void parse_request(const char *buffer, HttpRequest *req) {
    sscanf(buffer, "%15s %255s %15s", req->method, req->path, req->protocol);

    const char *body_start = strstr(buffer, "\r\n\r\n");
    if (body_start && strlen(body_start) > 4) {
        strncpy(req->body, body_start + 4, sizeof(req->body) - 1);
        req->body[sizeof(req->body) - 1] = '\0';
    }
}

void send_response(int sock, int code, const char *content_type, const char *body) {
    char response[BUFFER_SIZE];
    time_t now = time(NULL);
    char time_str[64];
    strftime(time_str, sizeof(time_str), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));

    snprintf(response, sizeof(response),
             "HTTP/1.1 %d %s\r\n"
             "Server: C HTTP Server\r\n"
             "Date: %s\r\n"
             "Access-Control-Allow-Origin: *\r\n"
             "Access-Control-Allow-Methods: POST, GET, OPTIONS\r\n"
             "Access-Control-Allow-Headers: Content-Type\r\n"
             "Content-Type: %s\r\n"
             "Content-Length: %zu\r\n"
             "Connection: close\r\n\r\n"
             "%s",
             code, code == 200 ? "OK" : "Not Found",
             time_str, content_type, strlen(body), body);

    write(sock, response, strlen(response));
}